# Copyright (c) 2007, Enrico Franchi
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the University of California, Berkeley nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

try:
    import cStringIO as StringIO
except ImportError:
    import StringIO

class InvalidPackage(Exception):
    pass

class _ConstantNamespace(type):
    def __iter__(cls):
        for v in cls.keys:
            yield v

class PackageKey(object):
    __metaclass__ = _ConstantNamespace
    
    NAME                   = 'name'
    VERSION                = 'version'
    REVISION               = 'revision'
    DIRECTORY              = 'directory'
    VARIANTS               = 'variants'
    HOMEPAGE               = 'homepage'
    DESCRIPTION            = 'description'
    BUILD_DEPENDENCIES     = 'build_dependencies'
    LIBRARY_DEPENDENCIES   = 'library_dependencies'
    RUNTIME_DEPENDENCIES   = 'runtime_dependencies'
    PLATFORMS              = 'platforms'
    MAINTAINERS            = 'maintainers'
    keys = [ locals()[key] for key in locals().keys() 
             if key.upper() == key and (key.isalpha() or key.endswith('_DEPENDENCIES'))]


class Package(object): 
    def __init__(self, d = None, **kargs):
        if d is None: d = {}
        d.update(kargs)
        for k in PackageKey:
            try:
                self.__setattr__(k, d[k])
            except KeyError:
                if k == PackageKey.NAME        : raise InvalidPackage('Name not provided')
                if k == PackageKey.VERSION     : raise InvalidPackage('Version not provided')
                if k == PackageKey.DIRECTORY   : raise InvalidPackage('Directory not provided')
                if k.endswith('s')    : self.__setattr__(k, [])
                if k == PackageKey.DESCRIPTION : self.__setattr__(k, '')
                if k == PackageKey.HOMEPAGE : self.__setattr__(k, '')
                if k == PackageKey.REVISION : self.__setattr__(k, None)
        
    def __getitem__(self, key):
        if key in PackageKey:
            return getattr(self, key)
        else:
            raise KeyError()
    
    # these functions need further configuration in order to
    # make them able to work both in the general print than in a 
    # field by field kind of print.
    
    def print_name(self, s):
        s.write(self.name)
        
    def print_version(self, s):
        s.write(self.version)
        
    def print_revision(self, s):
        if self.revision:
            s.write('Revision ')
            s.write(self.revision)
            s.write(', ')
            
    def print_directory(self, s):
        s.write(self.directory)
        
    def print_variants(self, s):
        if self.variants:
            s.write(' ')
            s.write('(Variants: ')
            s.write(', '.join(self.variants))
            s.write(')')
            
    def print_fline(self, s):
        self.print_name(s)
        s.write(' ')
        self.print_version(s)
        s.write(', ')
        self.print_revision(s)
        self.print_directory(s)
        self.print_variants(s)
        s.write('\n')
    
    def print_homepage(self, s):
        if self.homepage:
            s.write(self.homepage)
            s.write('\n')
    
    def print_description(self, s):
        if self.description:
            s.write('\n')
            s.write(self.description)
            s.write('\n')
            s.write('\n')

    def print_build_dependencies(self, s):
        if self.build_dependencies:
            s.write('Build Dependencies: ')
            s.write(', '.join(self.build_dependencies))
                                                       
    def print_library_dependencies(self, s):
        if self.library_dependencies:
            s.write('Library Dependencies: ')
            s.write(', '.join(self.library_dependencies))
            s.write('\n')
    
    def print_runtime_dependencies(self, s):
        if self.runtime_dependencies:
            s.write('Runtime Dependencies: ')                    
            s.write(', '.join(self.runtime_dependencies))
            s.write('\n')
    
    def print_platforms(self, s):
        s.write('Platforms: ')                    
        s.write(' '.join(self.platforms))    
        s.write('\n')
    
    def print_maintainers(self, s):
        s.write('Maintainers: ')                    
        s.write(' '.join(self.maintainers))
        s.write('\n')
    
    def print_package(self, s):
        self.print_fline(s)
        self.print_homepage(s)
        self.print_description(s)
        self.print_build_dependencies(s)
        self.print_library_dependencies(s)
        self.print_runtime_dependencies(s)
        self.print_platforms(s)
        self.print_maintainers(s)
        
    def __str__(self):
        s = StringIO.StringIO()
        self.print_package(s)
        s.seek(0)
        return s.read()

        
if __name__ == '__main__':
    p2 = Package(
        name                   = 'python25',
        revision               = '1',
        version                = '2.5',
        directory              = 'lang/python25',
        variants               = ['darwin_8'],
        homepage               = 'http://www.python.org/',
        description            = 'Python is an interpreted, interactive, object-oriented programming language.',
        library_dependencies   = [],
        runtime_dependencies   = [],
        platforms              = ['darwin'],
        maintainers            = ['mww@macports.org', 'pmq@macports.org']       
    )
    